import { Shader } from './Shader';
import { Texture } from './Texture';
import { Framebuffer, FramebufferCreateInfo } from './Framebuffer';

interface BlackHoleConfig {
  gravatationalLensing: boolean;
  renderBlackHole: boolean;
  mouseControl: boolean;
  cameraRoll: number;
  frontView: boolean;
  topView: boolean;
  adiskEnabled: boolean;
  adiskParticle: boolean;
  adiskDensityV: number;
  adiskDensityH: number;
  adiskHeight: number;
  adiskLit: number;
  adiskNoiseLOD: number;
  adiskNoiseScale: number;
  adiskSpeed: number;
}

export class BlackHoleRenderer {
  private canvas: HTMLCanvasElement;
  private gl: WebGLRenderingContext | null = null;
  private quadVAO: WebGLVertexArrayObject | null = null;
  private mouseX: number = 0;
  private mouseY: number = 0;
  private paused: boolean = false;
  private resizeObserver: ResizeObserver | null = null;
  private animationFrameId: number = 0;
  private startTime: number = 0;
  
  // 着色器
  private blackHoleShader: Shader | null = null;
  private passthroughShader: Shader | null = null;
  
  // 纹理
  private galaxyTexture: Texture | null = null;
  private colorMapTexture: Texture | null = null;
  private blackHoleTexture: Texture | null = null;
  
  // 帧缓冲
  private blackHoleFBO: Framebuffer | null = null;
  
  // 配置
  private config: BlackHoleConfig = {
    gravatationalLensing: true,
    renderBlackHole: true,
    mouseControl: true,
    cameraRoll: 0,
    frontView: false,
    topView: false,
    adiskEnabled: true,
    adiskParticle: true,
    adiskDensityV: 2.0,
    adiskDensityH: 4.0,
    adiskHeight: 0.55,
    adiskLit: 0.25,
    adiskNoiseLOD: 5.0,
    adiskNoiseScale: 0.8,
    adiskSpeed: 0.5
  };

  constructor(canvas: HTMLCanvasElement) {
    this.canvas = canvas;
  }

  async init(): Promise<boolean> {
    // 初始化WebGL上下文
    try {
      this.gl = this.canvas.getContext('webgl');
      if (!this.gl) {
        throw new Error('无法创建WebGL上下文');
      }
      
      // 创建四边形顶点缓冲
      this.createQuadBuffer();
      
      // 初始化着色器
      await this.initShaders();
      
      // 加载纹理
      await this.loadTextures();
      
      // 创建帧缓冲
      this.createFramebuffers();
      
      // 设置鼠标事件
      this.setupMouseEvents();
      
      // 设置窗口大小变化监听
      this.setupResizeObserver();
      
      // 记录开始时间
      this.startTime = performance.now();
      
      return true;
    } catch (error) {
      console.error('初始化失败:', error);
      return false;
    }
  }

  private createQuadBuffer(): void {
    const gl = this.gl;
    if (!gl) return;
    
    // 创建顶点数组对象(WebGL2)，如果支持的话
    // 对于WebGL1，我们使用仅使用缓冲
    const vertices = new Float32Array([
      -1.0, -1.0, 0.0,  // 左下
      -1.0,  1.0, 0.0,  // 左上
       1.0,  1.0, 0.0,  // 右上
       
       1.0,  1.0, 0.0,  // 右上
       1.0, -1.0, 0.0,  // 右下
      -1.0, -1.0, 0.0   // 左下
    ]);
    
    const vbo = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    
    // 启用顶点属性 - 注意在WebGL 1.0中，我们使用属性名称而非位置
    gl.enableVertexAttribArray(0);
    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
    
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
  }

  private async initShaders(): Promise<void> {
    const gl = this.gl;
    if (!gl) return;
    
    // 创建黑洞着色器
    this.blackHoleShader = new Shader(gl);
    await this.blackHoleShader.load('shader/simple.vert', 'shader/blackhole_main.frag');
    
    // 创建通道着色器
    this.passthroughShader = new Shader(gl);
    await this.passthroughShader.load('shader/simple.vert', 'shader/passthrough.frag');
  }

  private async loadTextures(): Promise<void> {
    const gl = this.gl;
    if (!gl) return;
    
    // 加载银河立方体贴图
    this.galaxyTexture = new Texture(gl);
    await this.galaxyTexture.loadCubemap([
      'assets/skybox_nebula_dark/right.png',
      'assets/skybox_nebula_dark/left.png',
      'assets/skybox_nebula_dark/top.png',
      'assets/skybox_nebula_dark/bottom.png',
      'assets/skybox_nebula_dark/front.png',
      'assets/skybox_nebula_dark/back.png'
    ]);
    
    // 加载颜色映射纹理
    this.colorMapTexture = new Texture(gl);
    await this.colorMapTexture.loadFromUrl('assets/color_map.png');
    
    // 创建黑洞渲染目标纹理
    this.blackHoleTexture = new Texture(gl);
    this.blackHoleTexture.createEmptyTexture(this.canvas.width, this.canvas.height);
  }

  private createFramebuffers(): void {
    const gl = this.gl;
    if (!gl || !this.blackHoleTexture) return;
    
    // 创建黑洞帧缓冲
    this.blackHoleFBO = new Framebuffer(gl);
    const info: FramebufferCreateInfo = {
      width: this.canvas.width,
      height: this.canvas.height,
      colorTexture: this.blackHoleTexture.getTexture() || undefined
    };
    this.blackHoleFBO.create(info);
  }

  private setupMouseEvents(): void {
    this.canvas.addEventListener('mousemove', (event) => {
      this.mouseX = event.clientX;
      this.mouseY = event.clientY;
    });
    
    // 可以添加键盘事件来调整参数
    window.addEventListener('keydown', (event) => {
      // 例如，按空格键暂停/继续
      if (event.code === 'Space') {
        this.paused = !this.paused;
        if (!this.paused) {
          this.start();
        } else {
          cancelAnimationFrame(this.animationFrameId);
        }
      }
    });
  }

  private setupResizeObserver(): void {
    this.resizeObserver = new ResizeObserver(() => {
      this.handleResize();
    });
    this.resizeObserver.observe(this.canvas);
    
    // 初始设置
    this.handleResize();
  }

  private handleResize(): void {
    const gl = this.gl;
    if (!gl) return;
    
    // 获取设备像素比
    const dpr = window.devicePixelRatio || 1;
    
    // 获取显示尺寸
    const displayWidth = this.canvas.clientWidth;
    const displayHeight = this.canvas.clientHeight;
    
    // 如果画布尺寸与显示尺寸不匹配，调整画布尺寸
    if (this.canvas.width !== displayWidth * dpr ||
        this.canvas.height !== displayHeight * dpr) {
      this.canvas.width = displayWidth * dpr;
      this.canvas.height = displayHeight * dpr;
      
      // 重新创建纹理和帧缓冲
      if (this.blackHoleTexture) {
        this.blackHoleTexture.createEmptyTexture(this.canvas.width, this.canvas.height);
      }
      
      if (this.blackHoleFBO && this.blackHoleTexture) {
        const info: FramebufferCreateInfo = {
          width: this.canvas.width,
          height: this.canvas.height,
          colorTexture: this.blackHoleTexture.getTexture() || undefined
        };
        this.blackHoleFBO.create(info);
      }
    }
    
    // 设置视口
    gl.viewport(0, 0, this.canvas.width, this.canvas.height);
  }

  start(): void {
    if (this.paused) return;
    
    this.render();
    this.animationFrameId = requestAnimationFrame(() => this.start());
  }

  private render(): void {
    const gl = this.gl;
    if (!gl || !this.blackHoleShader || !this.passthroughShader ||
        !this.galaxyTexture || !this.colorMapTexture || !this.blackHoleFBO) {
      return;
    }
    
    // 计算时间
    const currentTime = (performance.now() - this.startTime) / 1000.0;
    
    // 渲染黑洞到帧缓冲
    this.blackHoleFBO.bind();
    
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    
    this.blackHoleShader.use();
    
    // 设置uniform变量
    this.blackHoleShader.setUniform2f('resolution', this.canvas.width, this.canvas.height);
    this.blackHoleShader.setUniform1f('time', currentTime);
    this.blackHoleShader.setUniform1f('mouseX', this.mouseX);
    this.blackHoleShader.setUniform1f('mouseY', this.mouseY);
    
    // 设置黑洞配置
    this.blackHoleShader.setUniform1f('gravatationalLensing', this.config.gravatationalLensing ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('renderBlackHole', this.config.renderBlackHole ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('mouseControl', this.config.mouseControl ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('cameraRoll', this.config.cameraRoll);
    this.blackHoleShader.setUniform1f('frontView', this.config.frontView ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('topView', this.config.topView ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('adiskEnabled', this.config.adiskEnabled ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('adiskParticle', this.config.adiskParticle ? 1.0 : 0.0);
    this.blackHoleShader.setUniform1f('adiskDensityV', this.config.adiskDensityV);
    this.blackHoleShader.setUniform1f('adiskDensityH', this.config.adiskDensityH);
    this.blackHoleShader.setUniform1f('adiskHeight', this.config.adiskHeight);
    this.blackHoleShader.setUniform1f('adiskLit', this.config.adiskLit);
    this.blackHoleShader.setUniform1f('adiskNoiseLOD', this.config.adiskNoiseLOD);
    this.blackHoleShader.setUniform1f('adiskNoiseScale', this.config.adiskNoiseScale);
    this.blackHoleShader.setUniform1f('adiskSpeed', this.config.adiskSpeed);
    
    // 添加默认FOV缩放因子
    this.blackHoleShader.setUniform1f('fovScale', 1.0);
    
    // 绑定纹理
    this.galaxyTexture.bindAsCubemap(0);
    this.blackHoleShader.setUniform1i('galaxy', 0);
    
    this.colorMapTexture.bind(1);
    this.blackHoleShader.setUniform1i('colorMap', 1);
    
    // 绘制四边形
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    
    // 解绑帧缓冲，回到屏幕
    this.blackHoleFBO.unbind();
    
    // 将黑洞纹理渲染到屏幕
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    
    this.passthroughShader.use();
    
    // 设置uniform变量
    this.passthroughShader.setUniform2f('resolution', this.canvas.width, this.canvas.height);
    
    // 绑定黑洞纹理
    const blackHoleTexture = this.blackHoleFBO.getColorTexture();
    if (blackHoleTexture) {
      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, blackHoleTexture);
      this.passthroughShader.setUniform1i('texture0', 0);
    }
    
    // 绘制四边形
    gl.drawArrays(gl.TRIANGLES, 0, 6);
  }

  cleanup(): void {
    // 清理资源
    cancelAnimationFrame(this.animationFrameId);
    
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
    }
    
    if (this.blackHoleFBO) {
      this.blackHoleFBO.cleanup();
    }
    
    // 可以添加其他资源的清理
  }
} 